/* eslint-disable react/no-array-index-key */
import React from 'react'
import classNames from 'classnames'
import { RiLoaderLine } from '@remixicon/react'
import { TimelineItem } from './timelineItem'
import { withNativeProps } from '../../utils/native-props'
import type { TimelineProps } from './type'

const classPrefix = 'rt-timeline'

export const Timeline: React.FC<TimelineProps> = (props) => {
  const {
    mode = 'left',
    pending = null,
    pendingDot,
    reverse = false,
    children,
  } = props

  const pendingNode = typeof pending === 'boolean' ? null : pending

  const pendingItem = pending ? (
    <TimelineItem pending={!!pending} dot={pendingDot || <RiLoaderLine />}>
      {pendingNode}
    </TimelineItem>
  ) : null

  // 空节点（null，undefined 以及 布尔值）将在返回的数组中被忽略掉
  const timeLineItems = React.Children.toArray(children)
  timeLineItems.push(pendingItem!)
  if (reverse) { timeLineItems.reverse() }

  const getPosition = (ele: React.ReactElement<any>, idx: number) => {
    if (mode === 'alternate') {
      if (ele.props.position === 'right') return `${classPrefix}-item-right`
      if (ele.props.position === 'left') return `${classPrefix}-item-left`
      return idx % 2 === 0 ? `${classPrefix}-item-left` : `${classPrefix}-item-right`
    }
    if (mode === 'left') return `${classPrefix}-item-left`
    if (mode === 'right') return `${classPrefix}-item-right`
    throw new Error(`rt-timeline: mode [${mode}] error! should be one of 'left'、'right'、'alternate'!`)
  }

  const truthyItems = timeLineItems.filter((item) => !!item) as React.ReactElement<any, string | React.JSXElementConstructor<any>>[]
  const itemsCount = React.Children.count(truthyItems)
  const lastCls = `${classPrefix}-item-last`

  const items = truthyItems.map((ele, idx) => {
    // 存在pending节点时，倒数第二个为传入的最后节点
    const pendingClass = idx === itemsCount - 2 ? lastCls : ''
    // 没有pendding节点时，最后一个节点为传入的最后节点
    const noPendingClass = idx === itemsCount - 1 ? lastCls : ''
    return React.cloneElement(ele, {
      key: String(idx),
      className: classNames([
        ele.props.className,
        !reverse && !!pending ? pendingClass : noPendingClass,
        getPosition(ele, idx),
      ]),
    })
  })

  const hasLabelItem = truthyItems.some((item) => !!item?.props?.label)

  const classString = classNames(
    classPrefix,
    {
      [`${classPrefix}-pending`]: !!pending,
      [`${classPrefix}-reverse`]: !!reverse,
      [`${classPrefix}-${mode}`]: !!mode && !hasLabelItem,
      [`${classPrefix}-label`]: hasLabelItem,
      [`${classPrefix}-rtl`]: false,
    },
  )

  return withNativeProps(
    props,
    <ul
      className={classString}
    >
      {items}
    </ul>,
  )
}
